﻿/*
 * 
 * 
 * 参考网页：https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-history#c-version-70https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-8
 * 
 * 
*/

namespace CSharpNewFeatures;

public class CsharpDemo7 : CsharpDemoBase
{
    public override void Run()
    {
        Console.WriteLine("\n************************** CsharpDemo7  **************************");
        // 7.0.1 out 变量
        test70_1_out();

        // 7.0.2 元组和析构函数
        test70_2_tuple_decontruction();

        // 7.0.3 模式匹配
        // 7.0.4 本地函数
        // 7.0.5 扩展的 expression bodied 成员
        // 7.0.6 Ref 局部变量和返回结果

    }

    /// <summary>
    /// 演示元组和解构的用法，参见 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/builtin-types/value-tuples
    /// </summary>
    private void test70_2_tuple_decontruction()
    {
        // 1. 基本用法 
        (double, int) t1 = (4.5, 3);
        Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
        // Output:
        // Tuple with elements 4.5 and 3.

        (double Sum, int Count) t2 = (4.5, 3);
        Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
        // Output:
        // Sum of 3 elements is 4.5.

        (double, int) t3 = (4.5, 3);
        Console.WriteLine(t3.ToString());
        Console.WriteLine($"Hash code of {t3} is {t3.GetHashCode()}.");
        // Output:
        // (4.5, 3)
        // Hash code of (4.5, 3) is 718460086.

        // 支持超长
        var t4 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
        Console.WriteLine("t4=" + t4.ToString());
        Console.WriteLine($"下标从1开始： t4.Item1={t4.Item1}, t4.Item26={t4.Item26}");  // output: 26

        // 求最值
        var xs = new[] { 4, 7, 9 };
        var limits = FindMinMax(xs);
        Console.WriteLine($"Limits of [{string.Join(" ", xs)}] are {limits.min} and {limits.max}");
        // Output:
        // Limits of [4 7 9] are 4 and 9

        var ys = new[] { -9, 0, 67, 100 };
        var (minimum, maximum) = FindMinMax(ys);
        Console.WriteLine($"Limits of [{string.Join(" ", ys)}] are {minimum} and {maximum}");
        // Output:
        // Limits of [-9 0 67 100] are -9 and 100

        // 元组字段名称
        var t5 = (Sum: 4.5, Count: 3);
        Console.WriteLine($"Sum of {t5.Count} elements is {t5.Sum}.");

        (double Sum, int Count) t6 = (4.5, 3);
        Console.WriteLine($"Sum of {t6.Count} elements is {t6.Sum}.");

        // 元组赋值和析构
        (int, double) t7 = (17, 3.14);
        (double First, double Second) t8 = (0.0, 1.0);
        t8 = t7;
        Console.WriteLine($"{nameof(t8)}: {t8.First} and {t8.Second}");
        // Output:
        // t8: 17 and 3.14

        (double A, double B) t9 = (2.0, 3.0);
        t9 = t8;
        Console.WriteLine($"{nameof(t9)}: {t9.A} and {t9.B}");
        // Output:
        // t9: 17 and 3.14

        var t10 = ("post office", 3.6);
        var (destination, distance) = t10;
        Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
        // Output:
        // Distance to post office is 3.6 kilometers.

        // 元组相等, 只比较值，不比较类型。
        (int a, byte b) left = (5, 10);
        (long a, int b) right = (5, 10);
        Console.WriteLine(left == right);  // output: True
        Console.WriteLine(left != right);  // output: False

        var t11 = (A: 5, B: 10);
        var t12 = (B: 5, A: 10);
        Console.WriteLine(t11 == t12);  // output: True
        Console.WriteLine(t11 != t12);  // output: False

        // 28位有效数字
        decimal x = 0.99m;
        decimal y = 99999999999999999999999999m;
        Console.WriteLine("My amount = {0}", x);
        Console.WriteLine("Your amount = {0}", y);
        Console.WriteLine("Your amount = {0}", x + y);

        // 最后，元组也支持 out 关键字
    }

    (int min, int max) FindMinMax(int[] input)
    {
        if (input is null || input.Length == 0)
        {
            throw new ArgumentException("Cannot find minimum and maximum of a null or empty array.");
        }

        var min = int.MaxValue;
        var max = int.MinValue;
        foreach (var i in input)
        {
            if (i < min)
            {
                min = i;
            }
            if (i > max)
            {
                max = i;
            }
        }
        return (min, max);
    }

    private static void test70_1_out()
    {
        var v0 = double.TryParse("3.1415926", out double result1);
        var v1 = double.TryParse("3.14f15926", out double result2);
        Console.WriteLine($"v0: {v0}, result: {result1}");
        Console.WriteLine($"v1: {v1}, result: {result2}");
    }
}